const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'

/**
 * 运行一个微队列
 * 把传递的函数放到微队列中
 * @param {*} callback
 */
function runMicroTask(callback) {
  if (process?.nextTick) {
    process.nextTick(callback)
  } else {
    setTimeout(callback, 0)
  }
}

/**
 * 判断一个数据是否是 Promise
 * @param {Object} obj
 */
function isPromise(obj) {
  return !!(
    obj &&
    typeof obj === 'object' &&
    'then' in obj &&
    typeof obj.then === 'function'
  )
}

class MyPromise {
  #state = PENDING
  #value = void 0
  #handlers = []

  constructor(executor) {
    // 捕获异常
    try {
      executor(this.#resolve.bind(this), this.#reject.bind(this))
    } catch (error) {
      this.#reject(error)
    }
  }

  /**
   * 更新任务状态
   * @param {String} state 新状态
   * @param {any} data 相关数据
   * @returns
   */
  #checkStatus(state, data) {
    if (this.#state !== PENDING) return
    this.#state = state
    this.#value = data
    this.#runHandlers()
  }

  /**
   * 向处理队列中添加函数
   * @param {Function} executor 添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让 then 函数返回
   * @param {Function} reject 让 then 函数返回
   */
  #pushHandler(executor, state, resolve, reject) {
    this.#handlers.push({
      executor,
      state,
      resolve,
      reject
    })
  }

  /**
   * 根据实际情况执行队列
   */
  #runHandlers() {
    if (this.#state === PENDING) return
    while (this.#handlers[0]) {
      this.#runOneHandler(this.#handlers[0])
      this.#handlers.shift()
    }
  }

  /**
   * 处理一个 handler
   * @param {Object} handler
   */
  #runOneHandler({ state, executor, resolve, reject }) {
    runMicroTask(() => {
      if (this.#state !== state) return
      if (typeof executor !== 'function') {
        this.#state === FULFILLED ? resolve(this.#value) : reject(this.#value)
      }
      try {
        const result = executor(this.#value)
        if (isPromise(result)) {
          result.then(resolve, reject)
        } else {
          resolve(result)
        }
      } catch (error) {
        reject(error)
      }
    })
  }

  /**
   * 执行成功
   * @param {any} value
   */
  #resolve(value) {
    this.#checkStatus(FULFILLED, value)
  }

  /**
   * 执行失败
   * @param {any} value
   */
  #reject(reason) {
    this.#checkStatus(REJECTED, reason)
  }

  /**
   * Promise A+ 规范
   * @param {*} onFulfilled
   * @param {*} onRejected
   * @returns
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this.#pushHandler(onFulfilled, FULFILLED, resolve, reject)
      this.#pushHandler(onRejected, REJECTED, resolve, reject)
      this.#runHandlers()
    })
  }

  catch(onRejected) {
    return this.then(null, onRejected)
  }

  finally(onSettled) {
    return this.then(
      data => {
        onSettled()
        return data
      },
      error => {
        onSettled()
        throw error
      }
    )
  }

  /**
   * 返回一个已完成的 Promise
   * @param {any} data
   */
  static resolve(data) {
    if (data instanceof MyPromise) {
      return data
    }
    return new MyPromise((resolve, reject) => {
      if (isPromise(data)) {
        data.then(resolve, reject)
      } else {
        resolve(data)
      }
    })
  }

  /**
   * 得到一个被拒绝的 Promise
   * @param {*} reason
   */
  static reject(reason) {
    return new MyPromise((_resolve, reject) => {
      reject(reason)
    })
  }
}

const pro1 = new Promise((resolve, reject) => {
  resolve(1)
})

pro1
  .then(res => {
    console.log('🚀 ~ file: index.js:145 ~ res:', res)
    return new Promise(resolve => {
      resolve(2)
    })
  })
  .then(res => {
    console.log('🚀 ~ file: index.js:151 ~ res:', res)
  })
